#include "mmpf_usbuvch264.h"
#include "mmpf_usbuvc.h"
#include "mmpf_usbvend.h"
#include "pcam_msg.h"
#include "mmpf_mp4venc.h"
#include "mmpf_h264enc.h"
//#include "mmpd_h264enc.h"
#include "lib_retina.h"
#include "mmps_3gprecd.h"

#define  MB_MAX_POWER   (244800)
// Control H264 FrameRate
extern MMP_USHORT      gsVideoEncodeFPS ;
extern MMP_ULONG        glCustomTargetSizePerFrame;

//H264ControlMode         gbUVCXCtlMode = CBR_H264 ;
//UVCX_RateControlMode    gsUVCXCtlModeDef = { 0, CBR_H264        } ;
//UVCX_RateControlMode    gsUVCXCtlModeMin = { 0, CBR_H264        } ;
//UVCX_RateControlMode    gsUVCXCtlModeMax = { 0, CONSTANT_H264_QP} ;
UVCX_RateControlMode    gsUVCXCtlModeCur = { 0, CBR_H264        } ;

H264TemporalScaleMode   gbUVCXTemporalScaleMode = ONE_LAYER_H264;
H264SpatialScaleMode    gbUVCXSpatialScaleMode  = ONE_SPATIAL_LAYER;
H264SNRScaleMode        gbUVCXSNRScaleMode  = ONE_QUALITY_LAYER;
MMP_USHORT              gsUVCXVersion = 0x0100 ;
MMP_ULONG               glUVCXFrameRate = 0x51615;
UVCX_BitRateLayers      gsUVCXBitRate ;
H264PicType             gsUVCXPicTypeCtl ;
//UVCX_CropConfig         gsUVCXCropConfig ;

UVCX_VIDEO_CONFIG video_probe;
UVCX_PictureTypeCtl pict_type;
UVCX_FrameRateConfig fr;
//UVCX_BitRateLayers bitrate;

UVCX_VIDEO_CONFIG gsUVCXVideoConfigProbe_Def =
{
    333333, //  // Framerate : Change frame rate test ok
    3000000, // Bitrate : Change bitrate test ok
    0,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
    1280,       // wWidth
    720,                    // wHeight 
    0,//0,                      // wSliceSize
    SINGLE_SLICE,           // wSliceMode
    CONSTRAINED_BASELINE_P ,// wProfile
    //HIGH_P,
    100,//100,           // I-Frame period, 10 seconds test
    30, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    1,   // bUsageType
    1,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x00,   // bStreamMuxOption
    ANNEXB_H264, // bSliceFormat
    CAVLC_H264,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    1000,           // wLeakyBucketSize 
} ;

UVCX_VIDEO_CONFIG gsUVCXVideoConfigProbe_Cur =
{
    333333, //  // Framerate : Change frame rate test ok
    3000000, // Bitrate : Change bitrate test ok
    0,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
    1280,       // wWidth
    720,                    // wHeight 
    0,//0,                      // wSliceSize
    SINGLE_SLICE,           // wSliceMode
    CONSTRAINED_BASELINE_P ,// wProfile
    //HIGH_P,
    100,//100,           // I-Frame period, 10 seconds test
    30, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    1,   // bUsageType
    1,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x00,   // bStreamMuxOption
    ANNEXB_H264, // bSliceFormat
    CAVLC_H264,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    1000,           // wLeakyBucketSize 
} ;

UVCX_VIDEO_CONFIG gsUVCXVideoConfigProbe_Max =
{
    333333, //  // Framerate : Change frame rate test ok
#if SKYPE_H264_1080P
    6000000, // Bitrate : Change bitrate test ok
#else
    3000000, // Bitrate : Change bitrate test ok
#endif
    0xFFFF,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
#if SKYPE_H264_1080P
    1920,       // wWidth
    1080,                    // wHeight 
#else
    1280,       // wWidth
    720,                    // wHeight 
#endif
    0,//0,                      // wSliceSize
    SINGLE_SLICE,           // wSliceMode
    CONSTRAINED_BASELINE_P ,// wProfile
    //HIGH_P,
    50000,//100,           // I-Frame period, 10 seconds test
    30, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    1,   // bUsageType
    1,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x06,   // bStreamMuxOption
    ANNEXB_H264, // bSliceFormat
    CAVLC_H264,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    4000,           // wLeakyBucketSize 
} ;

UVCX_VIDEO_CONFIG gsUVCXVideoConfigProbe_Min =
{
    333333, //  // Framerate : Change frame rate test ok
    256000, // Bitrate : Change bitrate test ok
    0,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
    160,       // wWidth
    120,                    // wHeight 
    0,//0,                      // wSliceSize
    SINGLE_SLICE,           // wSliceMode
    CONSTRAINED_BASELINE_P ,// wProfile
    //HIGH_P,
    0,//100,           // I-Frame period, 10 seconds test
    0, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    1,   // bUsageType
    1,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x00,   // bStreamMuxOption
    ANNEXB_H264, // bSliceFormat
    CAVLC_H264,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    500,           // wLeakyBucketSize 
} ;

UVCX_PictureTypeCtl  gsUVCXPictureTypeControl =
{
    0,    // wLayerID
    PIC_IDR_WITH_NEW_SPSPPS,  // wPicType
};

UVCX_FrameRateConfig  gsUVCXFrameRateConfig =
{
    0,    // wLayerID
    0x51615,  // dwFrameInterval
};

UVCX_FrameRateConfig  gsUVCXFrameRateConfig_Max =
{
    0,    // wLayerID
    0x1E8480,  // dwFrameInterval
};

UVCX_AdvConfig        gsUVCXAdvConfig = 
{
    0,    // wLayerID
    MB_MAX_POWER,
    40,
    0
} ;

UVCX_BitRateLayers  gsUVCXBitRateLayers =
{
    0,    // wLayerID
    3000000,  // dwPeakBitrate
    3000000,  // dwAverageBitrate
};

UVCX_BitRateLayers  gsUVCXBitRateLayers_Def =
{
    0,    // wLayerID
    3000000,  // dwPeakBitrate
    3000000,  // dwAverageBitrate
};
UVCX_BitRateLayers  gsUVCXBitRateLayers_Min =
{
    0,    // wLayerID
    256000,  // dwPeakBitrate
    256000,  // dwAverageBitrate
};
UVCX_BitRateLayers  gsUVCXBitRateLayers_Max =
{
    0,    // wLayerID
    12000000,  // dwPeakBitrate
    12000000,  // dwAverageBitrate
};

UVCX_QPStepSize         gsUVCXQPStepSize =
{
    0,    // wLayerID
    0,    //bFrameType;
    0xFF, //bMinQp;
    0xFF  //bMaxQp;
};


// UVCX_VIDEO_CONFIG_PROBE
VC_CMD_CFG UVCX_VIDEO_CONFIG_PROBE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_VIDEO_CONFIG_PROBE_LEN,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Def,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Def,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Min,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Max,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Cur
} ;

// UVCX_VIDEO_CONFIG_COMMIT
VC_CMD_CFG UVCX_VIDEO_CONFIG_COMMIT_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_VIDEO_CONFIG_COMMIT_LEN,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Def,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Def,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Min,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Max,
    (CMD_VALUE)&gsUVCXVideoConfigProbe_Cur
} ;


VC_CMD_CFG UVCX_CONTROL_MODE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_CONTROL_MODE_LEN,
    (CMD_VALUE)1,(CMD_VALUE)0x010000,(CMD_VALUE)0x010000,(CMD_VALUE)0x030000,(CMD_VALUE)0x010000
} ; 

/*
VC_CMD_CFG UVCX_TEMPORAL_SCALE_MODE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_TEMPORAL_SCALE_MODE_LEN, 1,
    1,ONE_LAYER_H264,ONE_LAYER_H264,ONE_LAYER_H264,ONE_LAYER_H264

} ;

VC_CMD_CFG UVCX_SPATIAL_SCALE_MODE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_SPATIAL_SCALE_MODE_LEN, 1,
    1,ONE_SPATIAL_LAYER,ONE_SPATIAL_LAYER,ONE_SPATIAL_LAYER,ONE_SPATIAL_LAYER

} ;

VC_CMD_CFG UVCX_SNR_SCALE_MODE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_SNR_SCALE_MODE_LEN, 1,
    1,ONE_QUALITY_LAYER,ONE_QUALITY_LAYER,ONE_QUALITY_LAYER,ONE_QUALITY_LAYER

} ;
*/

VC_CMD_CFG UVCX_PICTURE_TYPE_CONTROL_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_PIC_TYPE_LEN,
    (CMD_VALUE)1,
    ((CMD_VALUE)((0xFFFF) << 16)),
    ((CMD_VALUE)((0x0001) << 16)),
    ((CMD_VALUE)((0x0002) << 16)),
    ((CMD_VALUE)((PIC_IDR_WITH_NEW_SPSPPS) << 16))
};

VC_CMD_CFG UVCX_VERSION_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_VERSION_LEN,
    (CMD_VALUE)0,(CMD_VALUE)0x0100,(CMD_VALUE)0x0100,(CMD_VALUE)0x0100,(CMD_VALUE)0x0100
};

VC_CMD_CFG UVCX_FRAMERATE_CONFIG_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_FRAMERATE_LEN,
    (CMD_VALUE)1,
    (CMD_VALUE)&gsUVCXFrameRateConfig,
    (CMD_VALUE)&gsUVCXFrameRateConfig,
    (CMD_VALUE)&gsUVCXFrameRateConfig_Max,
    (CMD_VALUE)&gsUVCXFrameRateConfig
};

VC_CMD_CFG UVCX_VIDEO_ADVANCE_CONFIG_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_ADVCONFIG_LEN,
    (CMD_VALUE)1,
    (CMD_VALUE)&gsUVCXAdvConfig,
    (CMD_VALUE)&gsUVCXAdvConfig,
    (CMD_VALUE)&gsUVCXAdvConfig,
    (CMD_VALUE)&gsUVCXAdvConfig
} ;

VC_CMD_CFG UVCX_BITRATE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_BITRATE_LEN,
    (CMD_VALUE)1,
    (CMD_VALUE)&gsUVCXBitRateLayers_Def,
    (CMD_VALUE)&gsUVCXBitRateLayers_Min,
    (CMD_VALUE)&gsUVCXBitRateLayers_Max,
    (CMD_VALUE)&gsUVCXBitRateLayers
} ;


VC_CMD_CFG UVCX_QP_STEPS_SIZE_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    UVCX_QPSTEP_SIZE_LEN,
    (CMD_VALUE)1,
    (CMD_VALUE)&gsUVCXQPStepSize,
    (CMD_VALUE)&gsUVCXQPStepSize,
    (CMD_VALUE)&gsUVCXQPStepSize,
    (CMD_VALUE)&gsUVCXQPStepSize
} ;


VC_CMD_CFG UVCX_ENCODER_RESET_CFG = {
    ( CAP_GET_INFO_CMD | CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_LEN_CMD | CAP_GET_RES_CMD | CAP_GET_DEF_CMD),
    ( INFO_GET_SUPPORT | INFO_SET_SUPPORT),
    0x02,
    (CMD_VALUE)0,(CMD_VALUE)0xFFFF,(CMD_VALUE)0,(CMD_VALUE)0,(CMD_VALUE)0
};


// 
UVCX_VIDEO_CONFIG gsCurH264Config =
{
    333333,     // Framerate : Change frame rate test ok
    3000000,    // Bitrate : Change bitrate test ok
    0,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
    1280,       // wWidth
    720,        // wHeight 
    0,          // wSliceSize
    SINGLE_SLICE,   // wSliceMode
    //CONSTRAINED_BASELINE_P ,// wProfile
    BASELINE_P ,// wProfile (Truman@121030, default use baseline instead of constrained baseline profile.)
    //HIGH_P,
#if (CUSTOMER == PNS) || (CUSTOMER == IPC) || (CUSTOMER == QDR) || (CUSTOMER == ANW)
    10,  // I-Frame period, 1 second = 1i30p
#else
    10000,      // I-Frame period, 10 seconds test
#endif    
    30, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    REALTIME_H264,   // bUsageType
    CBR_H264,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x00,   // bStreamMuxOption
    ANNEXB_H264, // bSliceFormat
    //CAVLC_H264,  // bEntropyCABAC;
    CABAC_H264,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    1000,           // wLeakyBucketSize 
} ;

// 
UVCX_VIDEO_CONFIG gsCurPreviewConfig =
{
    333333, //  // Framerate : Change frame rate test ok
    3000000, // Bitrate : Change bitrate test ok
    0,          // wNumConfigurations  : NA
    0,          // wConfigurationIndex : NA		 
    320,       // wWidth
    240,                    // wHeight 
    0,//0,                      // wSliceSize
    0,//SINGLE_SLICE,           // wSliceMode
    CONSTRAINED_BASELINE_P ,// wProfile
    //HIGH_P,
    0,//100,           // I-Frame period, 10 seconds test
    30, // wEstimateVideoDelay;	
    250, // wEstimatedMaxConfigDelay
    0,   // bUsageType
    0,   // bControlMode
    0,   // bTemporalScaleMode
    0,   // bSpatialScaleMode
    0,   // bSNRScaleMode
    0x00,   // bStreamMuxOption
    0, // bSliceFormat
    0,  // bEntropyCABAC;
    0,           // bTimestamp
    0,           // bInterFrmNum
    0,           // bPreviewFlipped
    0,           // bView;
    0,           // bReserved1
    0,           // bReserved2
    0,           // bStreamID
    0,           // bSpatialLayerRatio
    0,           // wLeakyBucketSize 
} ;

#if 1
void UVCX_SetCurVideoProbeConfig(UVCX_VIDEO_CONFIG *config_commit)
{
    gsUVCXVideoConfigProbe_Cur = *(UVCX_VIDEO_CONFIG *)config_commit ;
}
#else
void UVCX_SetCurVideoProbeConfig(UVCX_VIDEO_CONFIG *config_commit)
{
	gsUVCXVideoConfigProbe_Cur.dwFrameInterval = config_commit->dwFrameInterval;
	gsUVCXVideoConfigProbe_Cur.dwBitRate = config_commit->dwBitRate;
	gsUVCXVideoConfigProbe_Cur.wWidth = config_commit->wWidth;
	gsUVCXVideoConfigProbe_Cur.wHeight = config_commit->wHeight;
	gsUVCXVideoConfigProbe_Cur.wProfile = config_commit->wProfile;
	gsUVCXVideoConfigProbe_Cur.bStreamMuxOption = config_commit->bStreamMuxOption;
	gsUVCXVideoConfigProbe_Cur.bEntropyCABAC = config_commit->bEntropyCABAC;
	gsUVCXVideoConfigProbe_Cur.bTimestamp = config_commit->bTimestamp;
}
#endif


UVCX_VIDEO_CONFIG *UVCX_GetCurVideoProbeConfig(void)
{
    return (UVCX_VIDEO_CONFIG *)&gsUVCXVideoConfigProbe_Cur ;
}

//
// After commit , need call this function to update 
// new config into gsCurH264Config
//
#if 1
void UVCX_CommitH264Config(UVCX_VIDEO_CONFIG *config_commit)
{
    gsCurH264Config = *(UVCX_VIDEO_CONFIG *)config_commit ;
}
#else
void UVCX_CommitH264Config(UVCX_VIDEO_CONFIG *config_commit)
{
	gsCurH264Config.dwFrameInterval = config_commit->dwFrameInterval;
	gsCurH264Config.dwBitRate = config_commit->dwBitRate;
	gsCurH264Config.wWidth = config_commit->wWidth;
	gsCurH264Config.wHeight = config_commit->wHeight;
	gsCurH264Config.wProfile = config_commit->wProfile;
	gsCurH264Config.bStreamMuxOption = config_commit->bStreamMuxOption;
	gsCurH264Config.bEntropyCABAC = config_commit->bEntropyCABAC;
	gsCurH264Config.bTimestamp = config_commit->bTimestamp;
}
#endif

UVCX_VIDEO_CONFIG *UVCX_GetH264StartConfig(void)
{
    return (UVCX_VIDEO_CONFIG *)&gsCurH264Config ;
}

#if 1
void UVCX_CommitPreviewConfig(UVCX_VIDEO_CONFIG *config_commit)
{
    gsCurPreviewConfig = *(UVCX_VIDEO_CONFIG *)config_commit ;
}
#else
void UVCX_CommitPreviewConfig(UVCX_VIDEO_CONFIG *config_commit)
{
	gsCurPreviewConfig.dwFrameInterval = config_commit->dwFrameInterval;
//	gsCurPreviewConfig.dwBitRate = config_commit->dwBitRate;
	gsCurPreviewConfig.wWidth = config_commit->wWidth;
	gsCurPreviewConfig.wHeight = config_commit->wHeight;
//	gsCurPreviewConfig.wProfile = config_commit->wProfile;
	gsCurPreviewConfig.bStreamMuxOption = config_commit->bStreamMuxOption;
//	gsCurPreviewConfig.bEntropyCABAC = config_commit->bEntropyCABAC;
//	gsCurPreviewConfig.bTimestamp = config_commit->bTimestamp;
}
#endif

UVCX_VIDEO_CONFIG *UVCX_GetPreviewStartConfig(void)
{
    return (UVCX_VIDEO_CONFIG *)&gsCurPreviewConfig ;
}


//
// Startup setting called by PCAM_USB_PreviewStart()
//
MMP_USHORT UVCX_SetH264StartMode(UVCX_VIDEO_CONFIG *config)
{
    MMPF_VIDENC_QP_CTL      qc;
    MMPF_VIDENC_BITRATE_CTL BrCtl;
    MMPF_VIDENC_GOP_CTL     GopCtl;
    MMPF_VIDENC_SLICE_CTL   SliceCtl;
    MMPF_VIDENC_RC_MODE_CTL RcModeCtl;
    MMP_UBYTE               i, total_layers = ((config->bTemporoalScaleMode == TWO_LAYER_H264)? 2: 1);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    MMPS_3GPRECD_MODES  *vidrecdmodes = MMPS_3GPRECD_GetMode();
    
    if(MAX_VIDENC_NUM==2)
        vidrecdmodes->usVideoEncSubNum = 1;
    else
        vidrecdmodes->usVideoEncSubNum = 0;

#endif

    //dbg_printf(3,"#Enter UVC H264 v0.88 Commit Setting to H264 Kernel\r\n");
    if(!config) {
        return PCAM_USB_INIT_ERR ;
    }
    // 1. Convert H264 frame rate( from 100ns interval to FPS)
    UVCX_SetH264FrameRate(0, config->dwFrameInterval);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    if (vidrecdmodes->usVideoEncSubNum == 1) {
        UVCX_SetH264FrameRate(1, config->dwFrameInterval);
    }
#endif    
    
    //glCustomTargetSizePerFrame = config->dwBitRate / (8 * gsVideoEncodeFPS) ;
    BrCtl.ubLayerBitMap = 0;
    for (i = 0; i < total_layers; i++) {
        BrCtl.ubLayerBitMap |= (1 << i);
        BrCtl.ulBitrate[i]  = config->dwBitRate / total_layers;
    }
    //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_BR, (MMP_ULONG)&BrCtl);
    MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_BR, (void*)&BrCtl);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    if (vidrecdmodes->usVideoEncSubNum == 1) {
        //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_BR, (MMP_ULONG)&BrCtl);
        MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_BR, (void*)&BrCtl);
    }
#endif    

    // set init QP !
    qc.ubTID = TEMPORAL_ID_MASK;
        qc.ubQP[0] = 35;
        qc.ubQP[1] = 35;
        qc.ubQP[2] = 35;
        qc.ubTypeBitMap = 1 | (1 << 1) | (1 << 2); //I/P/B frames init qp
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_FRM_QP, (MMP_ULONG)&qc);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_FRM_QP, (void*)&qc);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_FRM_QP, (MMP_ULONG)&qc);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_FRM_QP, (void*)&qc);
        }
#endif    

    // 3. Slice mode
    if ((config->wSliceUnits==0)||(config->wSliceMode == SINGLE_SLICE)) { // Single slice per frame
        //MMPF_VIDENC_SetSliceSize(0, config->wHeight / 16);        
        //MMPF_VIDENC_SetSliceMode(0, MMPF_VIDENC_SLICE_MODE_ROW, 0xFFFF);
        SliceCtl.SliceMode = MMPF_VIDENC_SLICE_MODE_FRM;
        SliceCtl.ulSliceSize = 0;
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_SLICE_CTL, (void*)&SliceCtl);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetSliceSize(1, config->wHeight / 16);        
            //MMPF_VIDENC_SetSliceMode(1, MMPF_VIDENC_SLICE_MODE_ROW, 0xFFFF);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_SLICE_CTL, (void*)&SliceCtl);
        }
#endif    
    }
    else {
        MMP_BOOL slice_nr_ng = MMP_FALSE;
        if ((config->wSliceMode == MULTI_SLICE_NUMs)) {
            MMP_USHORT slice_row, mb_height;
            mb_height = (config->wHeight + 15)>>4;
            if (mb_height) {
                slice_row = (mb_height+config->wSliceUnits-1)/config->wSliceUnits;
                if (slice_row) {
                    MMP_USHORT slice_nr;
                    slice_nr = mb_height/slice_row + ((mb_height%slice_row)?1:0);
                    if (slice_nr == config->wSliceUnits){
                        //MMPF_VIDENC_SetSliceSize(0, slice_row);
                        //MMPF_VIDENC_SetSliceMode(0, MMPF_VIDENC_SLICE_MODE_ROW, 0xFFFF);
                        SliceCtl.SliceMode = MMPF_VIDENC_SLICE_MODE_ROW;
                        SliceCtl.ulSliceSize = slice_row;
                        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_SLICE_CTL, (void*)&SliceCtl);
                    }
                    else
                        slice_nr_ng = MMP_TRUE;
                }
                else
                    slice_nr_ng = MMP_TRUE;
            }
            else
                slice_nr_ng = MMP_TRUE;
        }
        else
            slice_nr_ng = MMP_TRUE;

        if (slice_nr_ng == MMP_TRUE) {
            dbg_printf(0,"#Invalid H264 Slice Mode, Unit:%d,%d\r\n",
                config->wSliceMode, config->wSliceUnits);
            return PCAM_USB_INIT_ERR ;
        }
    }
    
    // 4. Profile
    if(config->wProfile==CONSTRAINED_BASELINE_P) {
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (CONSTRAINED_FLAG_1<<8)|BASELINE_PROFILE);
//        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)((CONSTRAINED_FLAG_1 << 8)|BASELINE_PROFILE));
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)((0x40 << 8)|MAIN_PROFILE));
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, (CONSTRAINED_FLAG_1<<8)|BASELINE_PROFILE);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)((CONSTRAINED_FLAG_1<<8)|MAIN_PROFILE));
        }
#endif    
    } 
    else if(config->wProfile==BASELINE_P) {
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, BASELINE_PROFILE);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)MAIN_PROFILE);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, BASELINE_PROFILE);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)MAIN_PROFILE);
        }
#endif    
    } 
    else if(config->wProfile==HIGH_P) {
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, FREXT_HP);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)FREXT_HP);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, FREXT_HP);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)FREXT_HP);
        }
#endif    
    } 
    else if(config->wProfile==MAIN_P) {
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, MAIN_PROFILE);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)MAIN_PROFILE);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, MAIN_PROFILE);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_PROFILE, (void*)MAIN_PROFILE);
        }
#endif    
    }
    else {
        dbg_printf(0,"#Invalid H264 Profile:%d\r\n",config->wProfile);
        return PCAM_USB_INIT_ERR ;
    }
    
    // Level
    //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_LEVEL, gsUVCXAdvConfig.bLevel_idc);
    MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_LEVEL, (void*)(gsUVCXAdvConfig.bLevel_idc));
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_LEVEL, gsUVCXAdvConfig.bLevel_idc);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_LEVEL, (void*)(gsUVCXAdvConfig.bLevel_idc));
        }
#endif    

#if 0  // didn't support on VSN_V2    
    if (config->bTemporoalScaleMode == TWO_LAYER_H264) {
        if (config->wProfile==HIGH_P) {
            UVCX_SetH264TemporalScaleMode(TWO_LAYER_H264);
            MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_TSVC, MMP_TRUE);
        }
        else {
            dbg_printf(0,"#Invalid Only High Profile support 2 layer:%d\r\n", config->wProfile);
        }
    }
#endif
    
    // I Frame Period
    if(config->wIFramePeriod==0) {
        //MMPS_3GPRECD_SetPFrameCount(-1);
        #if (CUSTOMER == PNS) || (CUSTOMER == IPC) || (CUSTOMER == ANW)
        GopCtl.usGopSize = 300;
        #else
        GopCtl.usGopSize = 0xFFFF;
        #endif
        //dbg_printf(3,"#I-Frame #:%d\r\n",GopCtl.usGopSize);
    } else {
        MMP_ULONG period_ms = config->wIFramePeriod * 100 ;
        MMP_USHORT p_frame_c ;
        p_frame_c = ( gsVideoEncodeFPS * period_ms ) / 1000 ;
		dbg_printf(3,"#P-Frame #:%d, wIFramePeriod = %d\r\n",p_frame_c, config->wIFramePeriod);
        //MMPS_3GPRECD_SetPFrameCount(p_frame_c);
        GopCtl.usGopSize = p_frame_c;
    }
    GopCtl.usMaxContBFrameNum = 0;
    MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_GOP_CTL, (void*)&GopCtl);
    
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_CBR);
		MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_GOP_CTL, (void*)&GopCtl);
        }
#endif 
    // TBD : Control Mode , CBR,VBR,Constant QP
    if(config->bRateControlMode == CBR_H264) {
       // dbg_printf(3,"#CBR\r\n");
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_CBR;
        RcModeCtl.bLayerGlobalRc = MMP_FALSE;
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_CBR);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_CBR);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        }
#endif    
    } 
    else if(config->bRateControlMode == VBR_H264) {
       // dbg_printf(3,"#VBR\r\n");
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_VBR;
        RcModeCtl.bLayerGlobalRc = MMP_FALSE;
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_VBR);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_VBR);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        }
#endif    
    } 
    else if(config->bRateControlMode == CONSTANT_H264_QP) {
       // dbg_printf(3,"#Constant QP\r\n");
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_CQP;
        RcModeCtl.bLayerGlobalRc = MMP_FALSE;
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_CQP);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, MMPF_VIDENC_RC_METHOD_CQP);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
        }
#endif    
    }
    else {
        dbg_printf(0,"#Invalid H264 Control Mode:%d\r\n",config->bRateControlMode );
    }
    
    // TBD : Slice Format
    if(config->bSliceFormat==ANNEXB_H264) {
    } else {
        dbg_printf(0,"#Invalid H264 Bitstream Format\r\n");
    }
    // TBD : EntropyCABAC
    if(config->bEntropyCABAC) {
        
    } else {
    
    }
    // TBD :SEI timestamp
    if(config->bTimestamp) {
        MMPF_H264ENC_SetSeiEnable(0, MMP_TRUE);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            MMPF_H264ENC_SetSeiEnable(1, MMP_TRUE);
        }
#endif    
    } else {
        MMPF_H264ENC_SetSeiEnable(0, MMP_FALSE);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            MMPF_H264ENC_SetSeiEnable(1, MMP_FALSE);
        }
#endif    
    }
    // 
    if (config->wLeakyBucketSize) {
        MMPF_VIDENC_LEAKYBUCKET_CTL lb;
        lb.ubLayerBitMap = TEMPORAL_ID_MASK;
        for (i = 0; i < total_layers; i++) {
            lb.ulLeakyBucket[i] = config->wLeakyBucketSize;
        }
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_LB_SIZE, (MMP_ULONG)&lb);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_LB_SIZE, (void*)&lb);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_LB_SIZE, (MMP_ULONG)&lb);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_LB_SIZE, (void*)&lb);
        }
#endif    
    }
    
    #if 1 // Disalbe drop frame when storage / usage type
    if ( (config->bUsageType == STORAGE_H264)||(config->bUsageType == BROADCAST_H264)) {
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_SKIPPABLE, MMP_FALSE);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_SKIPPABLE, (void*)MMP_FALSE);
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if (vidrecdmodes->usVideoEncSubNum == 1) {
            //MMPF_VIDENC_SetStaticParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_SKIPPABLE, MMP_FALSE);
            MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_SKIPPABLE, (void*)MMP_FALSE);
        }
#endif    
    }
    #endif
    // Implement Flip by Sensor setting
    //UVCX_SetH264FlipMode(config->bPreviewFlipped);

    #if 0 //test sample code for adjust max i/b weight, p is always 1000
    {
    MMPF_VIDENC_PIC_WEIGHT_CTL wctl = {
	    0,      // single layer 0
	    0x01,   // bit 0 means I frame weight
	    1864,   // weight value, resolution 1000
	    0       // reserve for B frame weight
	};
    MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_PIC_MAX_WEIGHT, (MMP_ULONG)&wctl);
    }
    #endif
    return PCAM_ERROR_NONE;
}

// 3.3.3 UVCX_RATE_CONTROL_MODE
MMP_USHORT UVCX_SetH264ControlMode(UVCX_RateControlMode *ctlMode)
{
    //MMP_ULONG rc_method;
    MMPF_VIDENC_RC_MODE_CTL RcModeCtl;
#if USB_FRAMEBASE_DUAL_H264_STREAM
    MMPS_3GPRECD_MODES  *vidrecdmodes = MMPS_3GPRECD_GetMode();
#endif

    //gbUVCXCtlMode = ctlMode ;
    gsUVCXCtlModeCur = *ctlMode ;
    switch (gsUVCXCtlModeCur.bRateControlMode) {
    case CBR_H264:
        //rc_method = MMPF_VIDENC_RC_METHOD_CBR;
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_CBR;
        break;
    case VBR_H264:
        //rc_method = MMPF_VIDENC_RC_METHOD_VBR;
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_VBR;
        break;
    case CONSTANT_H264_QP:
        //rc_method = MMPF_VIDENC_RC_METHOD_CQP;
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_CQP;
        break;
    default:
        //rc_method = MMPF_VIDENC_RC_METHOD_CBR;
        RcModeCtl.RcMode = MMPF_VIDENC_RC_MODE_CBR;
        break;
    }

    RcModeCtl.bLayerGlobalRc = MMP_FALSE;
    MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
    //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, rc_method);
#if USB_FRAMEBASE_DUAL_H264_STREAM
    if (vidrecdmodes->usVideoEncSubNum == 1) {
        //MMPF_VIDENC_UpdateParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_METHOD, rc_method);
        MMPF_VIDENC_SetParameter(1, MMPF_VIDENC_ATTRIBUTE_RC_MODE, (void*)&RcModeCtl);
    }
#endif    

    return PCAM_ERROR_NONE ;    
}


// 3.3.4 UVCX_TEMPORAL_SCALE_MODE
MMP_USHORT UVCX_SetH264TemporalScaleMode(H264TemporalScaleMode tempScaleMode)
{
    gbUVCXTemporalScaleMode = tempScaleMode ;
    return PCAM_ERROR_NONE ;    
}

// 3.3.5 UVCX_SPATIAL_SCALE_MODE
MMP_USHORT UVCX_SetH264SpatialScaleMode(H264SpatialScaleMode spatialScaleMode)
{
    gbUVCXSpatialScaleMode = spatialScaleMode ;
    return PCAM_ERROR_NONE ;
}

// 3.3.6 UVCX_SNR_SCALE_MODE
MMP_USHORT UVCX_SetH264SNRScaleMode(H264SNRScaleMode snrScaleMode)
{
    gbUVCXSNRScaleMode = snrScaleMode ;
    return PCAM_ERROR_NONE ;
}


#if USB_FRAMEBASE_DUAL_H264_STREAM  //SetH264 BitRate and FrameRate Use
extern MMP_UBYTE XU_Ctrl_StreamID;
#endif
// 3.3.7 UVCX_BITRATE 
MMP_USHORT UVCX_SetH264BitRate(MMP_UBYTE ubEncId, UVCX_BitRateLayers *bRc)
{
    gsUVCXBitRate = *bRc ;

    //dbg_printf(3,"#H264 new bitrate :%d\r\n",gsUVCXBitRate.dwAverageBitrate);
    
    //if(gbUVCXCtlMode != CONSTANT_H264_QP) {
    if( gsUVCXCtlModeCur.bRateControlMode != CONSTANT_H264_QP) {
    // Following is come from currect bitrate control method.
        MMPF_VIDENC_BITRATE_CTL BrCtl;
        MMP_UBYTE i;
        BrCtl.ubLayerBitMap = 0;
        if (gbUVCXTemporalScaleMode == ONE_LAYER_H264) {
            BrCtl.ubLayerBitMap |= 1;
            BrCtl.ulBitrate[0]  = bRc->dwAverageBitrate;
        } else {
            for (i = 0; i < gbUVCXTemporalScaleMode; i++) {
                if (bRc->wLayerID & (1<<(LAYER_ID_BIT_SHIFT_TEMPORAL+i))) {
                    BrCtl.ubLayerBitMap |= (1 << i);
                    BrCtl.ulBitrate[i]  = bRc->dwAverageBitrate;
                }
            }
        }
        MMPF_VIDENC_SetParameter(ubEncId, MMPF_VIDENC_ATTRIBUTE_BR, (void*)&BrCtl);
        //MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_BR, (MMP_ULONG)&BrCtl);
        //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_BR, (MMP_ULONG)&BrCtl);
    }
    return PCAM_ERROR_NONE ;
}

// 3.3.8 UVCX_QPSTEP_SIZE
MMP_USHORT UVCX_SetH264QPStepSize(UVCX_QPStepSize *qStep)
{
    gsUVCXQPStepSize = *qStep ;

    if (qStep->bMinQp > qStep->bMaxQp) {
        qStep->bMaxQp = qStep->bMinQp;
    }
   // RTNA_DBG_Long(3, qStep->bMinQp);
   // RTNA_DBG_Long(3, qStep->bMaxQp);
    if (qStep->bFrameType & 0x01) {
       // RTNA_DBG_Str(3, " i frame qp bound\r\n");
        MMPF_VIDENC_SetQPBound(0, 0, MMPF_3GPMGR_FRAME_TYPE_I, qStep->bMinQp, qStep->bMaxQp);
    }
    if (qStep->bFrameType & 0x02) {
       // RTNA_DBG_Str(3, " p frame qp bound\r\n");
        MMPF_VIDENC_SetQPBound(0, 0, MMPF_3GPMGR_FRAME_TYPE_P, qStep->bMinQp, qStep->bMaxQp);
    }
    if (qStep->bFrameType & 0x04) {
      //  RTNA_DBG_Str(3, " b frame qp bound\r\n");
        MMPF_VIDENC_SetQPBound(0, 0, MMPF_3GPMGR_FRAME_TYPE_B, qStep->bMinQp, qStep->bMaxQp);
    }

    return PCAM_ERROR_NONE ;
}

// 3.3.9 UVCX_PICUTRE_TYPE_CONTROL
MMP_USHORT UVCX_SetH264PictureTypeCtl(H264PicType picType)
{
    gsUVCXPicTypeCtl = picType ;

    switch (gsUVCXPicTypeCtl) {
    case PIC_IDR_WITH_NEW_SPSPPS:
        //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, MMPF_VIDENC_PICCTL_IDR_RESYNC);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, (void*)MMPF_VIDENC_PICCTL_IDR_RESYNC);
        break;
    case PIC_IDR_FRAME:
        //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, MMPF_VIDENC_PICCTL_IDR);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, (void*)MMPF_VIDENC_PICCTL_IDR);
        break;
    case PIC_I_FRAME:
        //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, MMPF_VIDENC_PICCTL_I);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, (void*)MMPF_VIDENC_PICCTL_I);
        break;
    default:
        //MMPF_VIDENC_UpdateParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, MMPF_VIDENC_PICCTL_NONE);
        MMPF_VIDENC_SetParameter(0, MMPF_VIDENC_ATTRIBUTE_FORCE_I, (void*)MMPF_VIDENC_PICCTL_NONE);
        break;
    }

    return PCAM_ERROR_NONE ;
}


/*
// 3.3.11 UVCX_CROP_CONFIG
MMP_USHORT UVCX_SetH264CropConfig(UVCX_CropConfig *crop)
{
    MMPF_VIDENC_CROPPING    crop_offset;

    gsUVCXCropConfig = *crop;

    crop_offset.usTop   = crop->wCropTopOffset;
    crop_offset.usBottom = crop->wCropBottomOffset;
    crop_offset.usLeft  = crop->wCropLeftOffset;
    crop_offset.usRight = crop->wCropRightOffset;
    MMPF_VIDENC_SetStaticParameter(0, MMPF_VIDENC_ATTRIBUTE_CROPPING, (MMP_ULONG)&crop_offset);

    return PCAM_ERROR_NONE ;
}
*/

// 3.3.12 UVCX_FRAMERATE_CONFIG
// Input is 100ns BASE
MMP_USHORT UVCX_SetH264FrameRate(MMP_UBYTE ubEncId, MMP_ULONG frameInterval)
{ 
    MMP_USHORT fps  ;
    MMPF_VIDENC_MAX_FPS_CTL FpsCtl;

    glUVCXFrameRate = frameInterval ;
    if(glUVCXFrameRate) {
        fps = 10000000 / glUVCXFrameRate ;
    }
    if(fps < 5) fps = 5 ;
    else if(fps > 30) fps = 30; 
    
    gsVideoEncodeFPS = fps ;
    FpsCtl.ulMaxFpsResolution = gsVideoEncodeFPS*VIDEO_FPS_SCALE;
    FpsCtl.ulMaxFpsIncreament = VIDEO_FPS_SCALE;
    MMPF_VIDENC_SetParameter(ubEncId, MMPF_VIDENC_ATTRIBUTE_MAX_FPS, (void*)&FpsCtl);

    RTNA_DBG_Str(3,"FPS = ");
    MMPF_DBG_Int(gsVideoEncodeFPS, -2);
    RTNA_DBG_Str(3,"\r\n");        	
    
    return PCAM_ERROR_NONE ;
}

/*
MMP_USHORT UVCX_SetH264AdvConfig(UVCX_AdvConfig *advConfig)
{
    gsUVCXAdvConfig.bLevel_idc = advConfig->bLevel_idc ;    

    // static config
    //MMPD_H264ENC_SetLevel(0, advConfig->bLevel_idc);

    return PCAM_ERROR_NONE;
}


//
// USB_SetH264Resolution should be called before use this function
//
MMP_USHORT UVCX_GetH264EstimatedVideoDelay(MMP_USHORT *delay,MMP_USHORT *maxDelay)
{
#define DELAY_1080P      (30)
#define MAX_CONFIG_DELAY (250) // Don't know the meaning, just use value from spec. example

    MMP_USHORT d1=30,d2 = 33;
    PCAM_USB_INFO *pcamInfo = pcam_get_info();
    MMP_ULONG maxResSize = GetYUV420FrameSize(PCAM_USB_RESOL_1920x1080);
    MMP_ULONG curResSize = GetYUV420FrameSize(pcamInfo->pCamVideoRes);
    
    *delay = ( DELAY_1080P * curResSize) / maxResSize ;
    *maxDelay = MAX_CONFIG_DELAY ;
    dbg_printf(3,"#UVCX estimated (delay,maxdelay) : (%d,%d)\r\n");
    return PCAM_ERROR_NONE ;
    
}

//
// 0 : Normal (in spec.)
// 1 : Vertical Flip ,Mirror (in spec.)
// 2 : Horizontal Flip ( not in spec.)
// 3 : Both direction Flip (not in spec.)
MMP_USHORT UVCX_SetH264FlipMode(MMP_USHORT flip_id)
{
#if BIND_SENSOR_MT9T002==1    
    MMP_USHORT val = ISP_IF_SNR_ReadI2C(0x3040);
    MMP_USHORT val1 = val & 0x3FF ;
    if(flip_id==1) {
        val1 = ( val1 | 0x4000) ;
    }
    else if(flip_id==2) {
        val1 = ( val1 | 0x8000) ;
    }
    else if(flip_id==3) {
        val1 = ( val1 | 0xC000) ;
    }
    
    if(val!=val1) {
        ISP_IF_SNR_WriteI2C(0x3040,val1);
    }    
#endif    
}
*/

void UVCX_EnableSliceBasedTx(MMP_BOOL en)
{
#if SLOT_RING     
     MMPF_VIDENC_SetOutputSyncMode(en);
#else
     MMPF_VIDENC_SetOutputSyncMode(0);
#endif
     dbg_printf(3,"H264 slice-base Tx : %d\r\n", MMPF_VIDENC_GetOutputSyncMode());
}

MMP_BOOL UVCX_IsSliceBasedTx(void)
{
    return MMPF_VIDENC_GetOutputSyncMode();
}

MMP_USHORT UVCX_SetH264GOPCount(MMP_UBYTE ubEncId, MMP_ULONG GOPCnt)
{ 
    MMPF_VIDENC_GOP_CTL GopCtl;

    GopCtl.usGopSize = GOPCnt;
    GopCtl.usMaxContBFrameNum = 0;

    MMPF_VIDENC_SetParameter(ubEncId, MMPF_VIDENC_ATTRIBUTE_GOP_CTL, (void *) &GopCtl);

    RTNA_DBG_Str(3,"GOP = ");
    MMPF_DBG_Int(GOPCnt, -2);
    RTNA_DBG_Str(3,"\r\n");        	
    
    return PCAM_ERROR_NONE ;
}


